using System;
using System.Collections.Generic;
using Data;
using Framework.Audio;
using Framework.GamePool;
using Framework.Timer;
using Framework.UI;
using GameSystem;
using UnityEngine;
using View;

public class GameRoom
{

    public Dictionary<LightVector, Vector2Int> Vector2Ints = new Dictionary<LightVector, Vector2Int>()
                                                             {
                                                                 {LightVector.U, Vector2Int.up},
                                                                 {LightVector.UR, Vector2Int.up + Vector2Int.right},
                                                                 {LightVector.R, Vector2Int.right},
                                                                 {LightVector.DR, Vector2Int.down + Vector2Int.right},
                                                                 {LightVector.D, Vector2Int.down},
                                                                 {LightVector.DL, Vector2Int.down + Vector2Int.left},
                                                                 {LightVector.L, Vector2Int.left},
                                                                 {LightVector.UL, Vector2Int.up + Vector2Int.left},
                                                             };
    public LightController Scene { get; private set; }

    public GameRoomData GameRoomData { get; private set; }

    public int ActiveCount { get; private set; } = 0;

    public int NowLevel { get; private set; }
    
    public Dictionary<Vector2Int, GameCube> GridData { get; private set; } = new Dictionary<Vector2Int, GameCube>();

    public GameRoom() 
    {
        if (PlayerPrefs.HasKey("GameLevel"))
        {
            NowLevel = PlayerPrefs.GetInt("GameLevel");
        }
        else
        {
            NowLevel = 1;
        }
    }

    public bool SetLevel(int level)
    {
        PlayerPrefs.SetInt("GameLevel" , this.NowLevel);
        this.GridData.Clear();
        this.NowLevel = level;
        this.GameRoomData = Resources.Load<GameRoomData>($"Config/GameLevel/Level{level}");
        return this.GameRoomData != null;
        
    }

    public void CheckReceiverCount()
    {
        this.ActiveCount = 0;
        foreach (var vector2Int in GameRoomData.Receiver)
        {
            if (GridData[vector2Int].isLight)
            {
                this.ActiveCount += 1;
            }
        }
        if (this.ActiveCount == GameRoomData.Receiver.Length)
        {
            AudioManager.Instance.PlaySound("Game_complete");
            GameManager.Instance.IsGaming = false;
            //游戏完成
            UIManager.Instance.CloseView(UIPanel.GamePanel);
            //游戏动画
            this.Scene.OpenLight();
            GameUpdateMgr.Instance.CreateTimer(2, () => { GameManager.Instance.GameFsm.ChangeState(GameEnum.Win , this.NowLevel < 19); });
        }
    }

    public void CreateScene()
    {
        this.ClearScene();
        this.Scene = GamePoolMgr.Instance.InstantiatePoolObject<LightController>(this.GameRoomData.Level.ToString(), Vector3.zero, GameManager.Instance.World);
        this.Scene.CloseLight();
        GameUpdateMgr.Instance.CreateTimer(2,
                                           () =>
                                           {
                                               var launcher = GamePoolMgr.Instance.InstantiatePoolObject<GameLauncherCube>(GameObjectType.Launcher.ToString(), this.Scene.transform);
                                               launcher.transform.localPosition = this.ToV3(this.GameRoomData.Launcher);
                                               launcher.Point = new Vector2Int(this.GameRoomData.Launcher.x , this.GameRoomData.Launcher.y);
                                               this.GridData.Add(launcher.Point , launcher);
                                               foreach (var vector2 in this.GameRoomData.Obstacle)
                                               {
                                                   var cube = GamePoolMgr.Instance.InstantiatePoolObject<GameCube>(GameObjectType.Obstacle.ToString(), this.Scene.transform);
                                                   cube.transform.localPosition = this.ToV3(vector2);
                                                   cube.Point                   = new Vector2Int((int) vector2.x, (int) vector2.y);
                                                   this.GridData.Add(cube.Point , cube);
                                               }

                                               foreach (var vector2 in this.GameRoomData.Receiver)
                                               {
                                                   var cube = GamePoolMgr.Instance.InstantiatePoolObject<GameCube>(GameObjectType.Receiver.ToString(), this.Scene.transform);
                                                   cube.transform.localPosition = this.ToV3(vector2);
                                                   cube.Point                   = new Vector2Int((int) vector2.x, (int) vector2.y);
                                                   this.GridData.Add(cube.Point , cube);
                                               }

                                               GameUpdateMgr.Instance.CreateTimer(1, () => { UIManager.Instance.OpenView(UIPanel.GamePanel); });
                                           });
    }

    public bool AddCube(GameLightCube cube)
    {
        var point = new Vector2Int(Convert.ToInt16(cube.transform.position.x), Convert.ToInt16(cube.transform.position.z));
        int boder = GameRoomData.Level == GameLevel.Level3 ? 1 :(GameRoomData.Level == GameLevel.Level5 ? 2 : 4);  
        //边界检查
        if (Mathf.Abs(point.x) > boder || Mathf.Abs(point.y) > boder )
        {
            return false;
        }
        if (this.GridData.ContainsKey(point))
        {
            return false;
        }
        cube.OnInit(point);
        // Debug.Log($"原始位置：{cube.transform.position} , 归一位置：{cube.Point}");
        this.GridData.Add(cube.Point , cube);
        return true;
    }

    public bool RemoveCube(Vector2Int point) { return this.GridData.Remove(point); }

    public void ClearScene()
    {
        this.ActiveCount = 0;
        this.GridData.Clear();
        GamePoolMgr.Instance.DestoryAllObject();
    }

    private Vector3 ToV3(Vector2 vector2) { return new Vector3(vector2.x, 0, vector2.y); }

    public List<Vector2Int> ControlPoint(Vector2Int Center, LightVector vector)
    {
        var points = new List<Vector2Int>();
        var vector2 = Vector2Ints[vector];
        var count = this.GameRoomData.Level == GameLevel.Level3 ? 3 : this.GameRoomData.Level == GameLevel.Level5 ? 5 : 9;
        for (int i = 1; i <= count; i++)
        {
            var pos = Center + vector2 * i;
            if (Mathf.Abs(pos.x) > (count / 2 + 1) || Mathf.Abs(pos.y) > (count / 2 + 1))
            {
                break;
            }
            points.Add(pos);
            if (this.GridData.ContainsKey(pos))
            {
                break;
            }
        }
        return points;
    }
    public Vector2Int ControlEndPoint(Vector2Int Center, LightVector vector)
    {
        Vector2Int points  = Center;
        var vector2 = Vector2Ints[vector];
        var count   = this.GameRoomData.Level == GameLevel.Level3 ? 3 : this.GameRoomData.Level == GameLevel.Level5 ? 5 : 9;
        

        for (int i = 1; i <= count; i++)
        {
            var pos = Center + vector2 * i;
            if (Mathf.Abs(pos.x) > (count / 2 + 1) || Mathf.Abs(pos.y) > (count / 2 + 1))
            {
                break;
            }
            points = pos;
            if (this.GridData.ContainsKey(pos) && this.GridData[pos].IsActive)
            {
                break;
            }
        }
        // Debug.Log($"{Center} => {points} , v {vector2}");
        return points;
    }
}